﻿using System;
using System.Text;

namespace RxjhServer
{
	public class RC6
	{
		private const int m_nWord = 32;

		private const int r = 20;

		private const int c = 4;

		private string m_sEncryptionKey;

		public string m_sCryptedText;

		private int m_nChipherlen;

		private uint[] m_nKeyExpandBox;

		private uint[] n_WordBox;

		public Encoding Enc_default = Encoding.Unicode;

		public uint ROTL(uint x, uint y, int w)
		{
			return x << (int)(y & 255u) | x >> (int)((long)w - (long)((ulong)(y & 255u)));
		}

		public uint ROTR(uint x, uint y, int w)
		{
			return x >> (int)(y & 255u) | x << (int)((long)w - (long)((ulong)(y & 255u)));
		}

		public RC6()
		{
			this.IV = 16;
			this.m_nKeyExpandBox = new uint[8 * this.m_nChipherlen];
		}

		public RC6(int iv)
		{
			this.IV = iv;
			this.m_nKeyExpandBox = new uint[8 * this.m_nChipherlen];
		}

		public string KEY
		{
			get
			{
				return this.m_sEncryptionKey;
			}
			set
			{
				this.m_sEncryptionKey = value;
			}
		}

		public int IV
		{
			get
			{
				return this.m_nChipherlen;
			}
			set
			{
				this.m_nChipherlen = value;
			}
		}

		public int _IV()
		{
			if (this.m_nChipherlen < 16)
			{
				this.m_nChipherlen = 16;
			}
			if (this.m_nChipherlen > 32)
			{
				this.m_nChipherlen = 32;
			}
			return this.m_nChipherlen;
		}

		private char[] String_Unicode()
		{
			string text = this.m_sEncryptionKey;
			text = ((text.Length % this.m_nChipherlen != 0) ? text.PadRight(text.Length + (this.m_nChipherlen - text.Length % this.m_nChipherlen), '\0') : text);
			byte[] array = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, Encoding.Unicode.GetBytes(text));
			char[] array2 = new char[Encoding.ASCII.GetCharCount(array, 0, array.Length)];
			Encoding.ASCII.GetChars(array, 0, array.Length, array2, 0);
			return array2;
		}

		private void KeySteup()
		{
			uint num = 3084996963u;
			uint num2 = 2654435769u;
			uint num4;
			uint num3 = num4 = 0u;
			char[] array = this.String_Unicode();
			this.n_WordBox = new uint[this.m_nChipherlen / 4];
			int i;
			for (i = 0; i < this.m_nChipherlen; i++)
			{
				uint num5 = (uint)((uint)(array[i] & 'ÿ') << (8 * (i % 4) & 31));
				this.n_WordBox[i / 4] += num5;
			}
			this.m_nKeyExpandBox[0] = num;
			for (i = 1; i < 2 * this.m_nChipherlen + 4; i++)
			{
				this.m_nKeyExpandBox[i] = this.m_nKeyExpandBox[i - 1] + num2;
			}
			int j = 3 * Math.Max(this.n_WordBox.Length, 2 * this.m_nChipherlen + 4);
			i = 0;
			int num6 = 0;
			while (j > 0)
			{
				num4 = this.ROTL(this.m_nKeyExpandBox[num6] + num4 + num3, 3u, 32);
				this.m_nKeyExpandBox[num6] = (uint)((byte)num4);
				num3 += num4;
				num3 = this.ROTL(this.n_WordBox[i] + num4 + num3, num4 + num3, 32);
				this.n_WordBox[i] = num3;
				num6 = (num6 + 1) % (2 * this.m_nChipherlen + 4);
				i = (i + 1) % this.n_WordBox.Length;
				j--;
			}
		}

		public string Encrypt(string str, string prssword)
		{
			str = ((str.Length % 32 != 0) ? str.PadRight(str.Length + (32 - str.Length % 32), '\0') : str);
			this.KEY = prssword;
			this.KeySteup();
			uint num4;
			uint num3;
			uint num2;
			uint num = num2 = (num3 = (num4 = 0u));
			byte[] bytes = Encoding.Unicode.GetBytes(str);
			char[] chars = new char[Encoding.ASCII.GetCharCount(bytes, 0, bytes.Length)];
			Encoding.ASCII.GetChars(bytes, 0, bytes.Length, chars, 0);
			byte[] array = new byte[bytes.Length];
			for (int i = 0; i < 4; i++)
			{
				num2 += (uint)((uint)(bytes[2 * i] & 255) << 8 * i);
				num += (uint)((uint)(bytes[2 * i + 8] & 255) << 8 * i);
				num3 += (uint)((uint)(bytes[2 * i + 16] & 255) << 8 * i);
				num4 += (uint)((uint)(bytes[2 * i + 24] & 255) << 8 * i);
			}
			num += this.m_nKeyExpandBox[0];
			num4 += this.m_nKeyExpandBox[1];
			for (int j = 1; j <= this.m_nChipherlen; j++)
			{
				uint num5 = this.ROTL(num4 * (2u * num4 + 1u), 5u, 32);
				uint num6 = this.ROTL(num * (2u * num + 1u), 5u, 32);
				num2 = this.ROTL(num2 ^ num6, num5, 32) + this.m_nKeyExpandBox[2 * j];
				num3 = this.ROTL(num3 ^ num5, num6, 32) + this.m_nKeyExpandBox[2 * j + 1];
				uint num7 = num2;
				num2 = num;
				num = num3;
				num3 = num4;
				num4 = num7;
			}
			uint[] array2 = new uint[4];
			num2 += this.m_nKeyExpandBox[42];
			num3 += this.m_nKeyExpandBox[43];
			array2[0] = num2;
			array2[1] = num;
			array2[2] = num3;
			array2[3] = num4;
			for (int k = 0; k < 4; k++)
			{
				array[2 * k] = (byte)(array2[0] >> 8 * k & 255u);
				array[2 * k + 8] = (byte)(array2[1] >> 8 * k & 255u);
				array[2 * k + 16] = (byte)(array2[2] >> 8 * k & 255u);
				array[2 * k + 24] = (byte)(array2[3] >> 8 * k & 255u);
			}
			char[] array3 = new char[array.Length];
			Encoding.Unicode.GetChars(array, 0, array.Length, array3, 0);
			this.m_sCryptedText = new string(array3, 0, array3.Length);
			this.Enc_default.GetBytes(this.m_sCryptedText);
			return this.m_sCryptedText;
		}

		public string Decrypt(string str, string prssword)
		{
			str = ((str.Length % 32 != 0) ? str.PadRight(str.Length + (32 - str.Length % 32), '\0') : str);
			this.KEY = prssword;
			this.KeySteup();
			uint num4;
			uint num3;
			uint num2;
			uint num = num2 = (num3 = (num4 = 0u));
			byte[] bytes = this.Enc_default.GetBytes(str);
			byte[] array = new byte[bytes.Length];
			for (int i = 0; i < 4; i++)
			{
				num2 += (uint)((uint)(bytes[2 * i] & 255) << 8 * i);
				num += (uint)((uint)(bytes[2 * i + 8] & 255) << 8 * i);
				num3 += (uint)((uint)(bytes[2 * i + 16] & 255) << 8 * i);
				num4 += (uint)((uint)(bytes[2 * i + 24] & 255) << 8 * i);
			}
			num3 -= this.m_nKeyExpandBox[43];
			num2 -= this.m_nKeyExpandBox[42];
			for (int j = 1; j <= this.m_nChipherlen; j++)
			{
				uint num5 = num4;
				num4 = num3;
				num3 = num;
				num = num2;
				num2 = num5;
				uint num6 = this.ROTL(num4 * (2u * num4 + 1u), 5u, 32);
				uint num7 = this.ROTL(num * (2u * num + 1u), 5u, 32);
				num3 = (this.ROTR(num3 - this.m_nKeyExpandBox[2 * (this.m_nChipherlen - j) + 3], num7, 32) ^ num6);
				num2 = (this.ROTR(num2 - this.m_nKeyExpandBox[2 * (this.m_nChipherlen - j) + 2], num6, 32) ^ num7);
			}
			num4 -= this.m_nKeyExpandBox[1];
			num -= this.m_nKeyExpandBox[0];
			for (int k = 0; k < 4; k++)
			{
				array[2 * k] = (byte)(num2 >> 8 * k & 255u);
				array[2 * k + 8] = (byte)(num >> 8 * k & 255u);
				array[2 * k + 16] = (byte)(num3 >> 8 * k & 255u);
				array[2 * k + 24] = (byte)(num4 >> 8 * k & 255u);
			}
			char[] array2 = new char[this.Enc_default.GetCharCount(array, 0, array.Length)];
			this.Enc_default.GetChars(array, 0, array.Length, array2, 0);
			this.m_sCryptedText = new string(array2, 0, array2.Length);
			this.Enc_default.GetBytes(this.m_sCryptedText);
			return this.m_sCryptedText;
		}
	}
}
